import os
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score, f1_score,accuracy_score
from sklearn.svm import SVC
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import BernoulliNB

mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['font.serif'] = ['KaiTi']
# mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题,或者转换负号为字符串

# ----------------------------------------------------------------------------------
# 第一步 切分训练集和测试集
# ----------------------------------------------------------------------------------

# X = []  # 定义图像名称
# Y = []  # 定义图像分类类标
# Z = []  # 定义图像像素'''

df = pd.read_excel('C:/Users/zlsjNKJS/Desktop/090-2/train.xlsx')

def remove_extension(filename):
    return os.path.splitext(filename)[0]

def extract_hog_features(image):
    winSize = (256, 256)
    blockSize = (64, 64)
    blockStride = (8, 8)
    cellSize = (16, 16)
    nbins = 9
    hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)
    return hog.compute(image)

def extract_color_histogram(image, bins=32):
    hist=cv2.calcHist([image],[0,1,2],None,[bins,bins,bins],[0,256,0,256,0,256])
    return hist.flatten()


df.iloc[:, 1] = df.iloc[:, 1].apply(remove_extension)

df.to_excel('C:/Users/zlsjNKJS/Desktop/090-2/modified_train.xlsx')

X_train_str = df.iloc[:, 1].tolist()
Y_train_str_excel = df.iloc[:, 11].tolist()

X_train = [int(item) for item in X_train_str]
Y_train_excel = [item for item in Y_train_str_excel]

print("X_train:", X_train)
print("Y_train:", Y_train_excel)

df = pd.read_excel('C:/Users/zlsjNKJS/Desktop/090-2/val.xlsx')

df.iloc[:, 1] = df.iloc[:, 1].apply(remove_extension)

df.to_excel('C:/Users/zlsjNKJS/Desktop/090-2/modified_val.xlsx')

X_val_str = df.iloc[:, 1].tolist()
Y_val_excel = df.iloc[:, 11].tolist()

X_val = [int(item) for item in X_val_str]

print("X_val:", X_val)
print("Y_val:", Y_val_excel)

print(len(X_train), len(X_val), len(Y_train_excel), len(Y_val_excel))

# ----------------------------------------------------------------------------------
# 第二步 图像读取及转换为像素直方图
# ----------------------------------------------------------------------------------

# 训练集
XX_train = []
for file_name in X_train_str:
    file_path = os.path.join('C:/Users/zlsjNKJS/Desktop/090-2/train', str(file_name)+'.jpg')
    image = cv2.imread(file_path, cv2.IMREAD_COLOR)

    if image is not None:
        # 图像像素大小一致
        img = cv2.resize(image, (256, 256),
                         interpolation=cv2.INTER_CUBIC)

        #提取HoG特征
        hog_features=extract_hog_features(img)

        # 计算图像直方图并存储至X数组
        color_hist_features=extract_color_histogram(img)

        features = np.hstack((hog_features, color_hist_features))

        XX_train.append(features)
    else:
        print(f"Image not found or cannot be read:{file_path}")

# 测试集
XX_val = []
for file_name in X_val_str:
    file_path = os.path.join('C:/Users/zlsjNKJS/Desktop/090-2/val', str(file_name) + '.jpg')
    image = cv2.imread(file_path, cv2.IMREAD_COLOR)

    if image is not None:
        # 图像像素大小一致
        img = cv2.resize(image, (256, 256),
                         interpolation=cv2.INTER_CUBIC)

        # 提取HoG特征
        hog_features = extract_hog_features(img)

        # 计算图像直方图并存储至X数组
        color_hist_features = extract_color_histogram(img)

        features = np.hstack((hog_features, color_hist_features))

        XX_val.append(features)
    else:
        print(f"Image not found or cannot be read:{file_path}")

XX_train = np.array(XX_train)
XX_val = np.array(XX_val)

precision_all = []
recall_all = []
f1_all = []
accuracy_all = []

for ljl in range(30,60):
    sjy = 0.01 * ljl
    print(sjy)
    Y_train = []
    Y_val = []
    for i in range(len(Y_train_excel)):
        if Y_train_excel[i]<sjy:
            Y_train.append(0)
        else:
            Y_train.append(1)
    for i in range(len(Y_val_excel)):
        if Y_val_excel[i]<sjy:
            Y_val.append(0)
        else:
            Y_val.append(1)
    # SVM
    '''clf = SVC(kernel="linear").fit(XX_train, Y_train)
    predictions_labels = clf.predict(XX_val)'''
    # 决策树
    '''clf = DecisionTreeClassifier().fit(XX_train, Y_train)
    predictions_labels = clf.predict(XX_val)'''
    # KNN
    '''clf = KNeighborsClassifier(n_neighbors=11).fit(XX_train, Y_train)
    predictions_labels = clf.predict(XX_val)'''
    # 贝叶斯
    clf = BernoulliNB().fit(XX_train, Y_train)
    predictions_labels = clf.predict(XX_val)
    y_true = Y_val  # 正确标签
    y_pred = predictions_labels  # 预测标签
    labels = [0,1]
    tick_marks = np.array(range(len(labels))) + 0.5

    print(u'预测结果:')
    print(predictions_labels)
    print(u'算法评价:')
    precision = precision_score(y_true, y_pred, average='weighted')
    recall = recall_score(y_true, y_pred, average='weighted')
    f1 = f1_score(y_true, y_pred, average='weighted')
    acc=accuracy_score(y_true, y_pred)
    print(f"Precision:{precision:.2f}")
    print(f"Recall:{recall:.2f}")
    print(f"F1 Score:{f1:.2f}")
    print(f"Accuracy:{acc:.2f}")
    precision_all.append(precision)
    recall_all.append(recall)
    f1_all.append(f1)
    accuracy_all.append(acc)
    cm = confusion_matrix(y_true, y_pred)
    print(cm)
print(precision_all)
print(recall_all)
print(f1_all)
print(accuracy_all)

thresholds = [0.01 * i for i in range(30,60)]
plt.figure(figsize=(15,8))

plt.subplot(221)
plt.plot(thresholds, precision_all, marker='o')
plt.title('Precision For Different Thresholds')
plt.xlabel('Threshold')
plt.ylabel('Precision')

plt.subplot(222)
plt.plot(thresholds, recall_all, marker='o')
plt.title('Recall For Different Thresholds')
plt.xlabel('Threshold')
plt.ylabel('Recall')

plt.subplot(223)
plt.plot(thresholds, f1_all, marker='o')
plt.title('F1 Score For Different Thresholds')
plt.xlabel('Threshold')
plt.ylabel('F1 Score')

plt.subplot(224)
plt.plot(thresholds, accuracy_all, marker='o')
plt.title('Accuracy For Different Thresholds')
plt.xlabel('Threshold')
plt.ylabel('Accuracy')

plt.tight_layout()
plt.show()











'''def plot_confusion_matrix(cm, title='Confusion Matrix', cmap=plt.cm.Blues):
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    xlocations = np.array(range(len(labels)))
    plt.xticks(xlocations, labels, rotation=90)
    plt.yticks(xlocations, labels)
    plt.ylabel('True label')
    plt.xlabel('Predicted label')


cm = confusion_matrix(y_true, y_pred)
print(cm)
np.set_printoptions(precision=2)
cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
print(cm_normalized)
plt.figure(figsize=(12, 8), dpi=120)

ind_array = np.arange(len(labels))
x, y = np.meshgrid(ind_array, ind_array)

for x_val, y_val in zip(x.flatten(), y.flatten()):
        c = cm_normalized[y_val][x_val]
        if c > 0.01:
            plt.text(x_val, y_val, "%0.2f" % (c,), color='red', fontsize=7, va='center', ha='center')
# offset the tick
plt.gca().set_xticks(tick_marks, minor=True)
plt.gca().set_yticks(tick_marks, minor=True)
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.grid(True, which='minor', linestyle='-')
plt.gcf().subplots_adjust(bottom=0.15)

plot_confusion_matrix(cm_normalized, title='Normalized confusion matrix')
# show confusion matrix
plt.savefig('matrix.png', format='png')
plt.show()'''